#ifndef GAME_CPP
#define GAME_CPP
#include "cell.h"
using namespace std;

cell::cell()
{
    cout << "constructing from the builder..." << endl;
    ini();
}
cell::cell(int l, int w, int n)
{
    lenth = l;
    width = w;
    num = n;
    cout << "constructing..." << endl;
    ini();
}
void cell::ini()
{
    for (int i = 1; i <= (lenth + 2) * (width + 2); i++)
        cells[i] = '0';
    for (int i = 2; i <= lenth + 1; i++)
        cells[i] = '#';
    for (int i = (lenth + 2) * (width + 1) + 2; i <= (lenth + 2) * (width + 2) + 1; i++)
        cells[i] = '#';
    for (int i = lenth + 2; i <= (lenth + 2) * (width + 2); i += (lenth + 2))
        cells[i] = '#';
    for (int i = 1; i <= (lenth + 2) * (width + 1) + 1; i += (lenth + 2))
        cells[i] = '#';
    for (int i = 1; i <= (lenth + 2) * (width + 2); i++)
        curtain[i] = '#';
    Mine();
    counter();
}
void cell::Mine()
{
    srand(time(NULL));
    int temp = num;
    for (int i = 1; i <= num; i++)
    {
        int M = rand() % (lenth * width) + 1;
        if (cells[M + lenth + 3 + 2 * ((M - 1) / lenth)] == '*')
        {
            num += 1;
        }
        else
        {
            cells[M + lenth + 3 + 2 * ((M - 1) / lenth)] = '*';
        }
    }
    num = temp;
}
void cell::PR1()
{
    for (int i = 1; i <= lenth * width; i++)
    {
        cout << curtain[i + lenth + 3 + 2 * ((i - 1) / lenth)] << ' ';
        if (i % lenth == 0)
            cout << endl;
    }
    cout << endl;
}
void cell::PR2()
{
    for (int i = 1; i <= lenth * width; i++)
    {
        cout << cells[i + lenth + 3 + 2 * ((i - 1) / lenth)] << ' ';
        if (i % lenth == 0)
            cout << endl;
    }
    cout << endl;
}
cell::~cell()
{
    cout << "destructing..." << endl;
}
void cell::counter()
{
    for (int i = 1; i <= lenth * width; i++)
    {
        if (!jug(i, '*'))
        {
            if (jug(i + 1, '*') && i % lenth != 0)
                plus(i);
            if (jug(i - 1, '*') && i % lenth != 1)
                plus(i);
            if (jug(i + lenth, '*') && (i - 1) / lenth != width)
                plus(i);
            if (jug(i - lenth, '*') && i > lenth)
                plus(i);
            if (jug(i + lenth + 1, '*') && (i - 1) / lenth != width && i % lenth != 0)
                plus(i);
            if (jug(i + lenth - 1, '*') && (i - 1) / lenth != width && i % lenth != 1)
                plus(i);
            if (jug(i - lenth - 1, '*') && i > lenth && i % lenth != 1)
                plus(i);
            if (jug(i - lenth + 1, '*') && i > lenth && i % lenth != 0)
                plus(i);
        }
    }
}
void cell::show(int tr)
{
    curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] = cells[tr + lenth + 3 + 2 * ((tr - 1) / lenth)];
}
void cell::process(int tr)
{
    show(tr);
    if (jug(tr, '0'))
    {
        expand('0', tr);
    }
    if (jug(tr, '*'))
    {
        flg1 = false;
        flg2 = false;
    }
    int cnt = 0;
    for (int i = 1; i <= lenth * width; i++)
    {
        if (jugc(i, '#') || jugc(i, 'M'))
            cnt++;
    }
    if (cnt == num && flg2 == true)
    {
        flg1 = false;
        flg2 = true;
    }
    fin();
}
bool cell::jug(int tr, char x)
{
    if (cells[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == x)
        return true;
    else
        return false;
}
bool cell::jugc(int tr, char x)
{
    if (curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == x)
        return true;
    else
        return false;
}
void cell::plus(int tr)
{
    cells[tr + lenth + 3 + 2 * ((tr - 1) / lenth)]++;
}
void cell::discover()
{
    PR1();
    int cnt = 0;
    while (flg1 && cin >> mark >> x >> y)
    {
        cnt++;
        long long tr = (x - 1) * lenth + y;
        if (mark == 'D')
        {
            while (cnt == 1 && cells[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == '*')
            {
                ini();
            }
            if (jugc(tr, '#'))
                process(tr);
            if (flg1)
                PR1();
        }
        if (mark == 'M')
        {
            sign(tr);
        }
        if (mark == 'R')
        {
            detect(tr);
        }
    }
}
void cell::expand(char x, int tr)
{
    if (x == 'u')
    {
        if (tr > lenth)
            show(tr - lenth);
        if (tr > lenth && tr % lenth != 1)
            show(tr - lenth - 1);
        if (tr > lenth && tr % lenth != 0)
            show(tr - lenth + 1);
        if (jug(tr - lenth - 1, '0') && tr > lenth && tr % lenth != 1)
            expand('u', 'l', tr - lenth - 1);
        if (jug(tr - lenth + 1, '0') && tr > lenth && tr % lenth != 0)
            expand('u', 'r', tr - lenth + 1);
        if (jug(tr - lenth, '0') && tr > lenth)
            expand('u', tr - lenth);
        Sleep(100);
    }
    if (x == 'd')
    {
        if ((tr - 1) / lenth != width)
            show(tr + lenth);
        if ((tr - 1) / lenth != width && tr % lenth != 0)
            show(tr + lenth + 1);
        if ((tr - 1) / lenth != width && tr % lenth != 1)
            show(tr + lenth - 1);
        if (jug(tr + lenth - 1, '0') && (tr - 1) / lenth != width && tr % lenth != 1)
            expand('d', 'l', tr + lenth - 1);
        if (jug(tr + lenth + 1, '0') && (tr - 1) / lenth != width && tr % lenth != 0)
            expand('d', 'r', tr + lenth + 1);
        if (jug(tr + lenth, '0') && (tr - 1) / lenth != width)
            expand('d', tr + lenth);
        Sleep(100);
    }
    if (x == 'r')
    {
        if (tr % lenth != 0)
            show(tr + 1);
        if (tr > lenth && tr % lenth != 0)
            show(tr - lenth + 1);
        if ((tr - 1) / lenth != width && tr % lenth != 0)
            show(tr + lenth + 1);
        if (jug(tr + lenth + 1, '0') && (tr - 1) / lenth != width && tr % lenth != 0)
            expand('r', 'd', tr + lenth + 1);
        if (jug(tr - lenth + 1, '0') && tr > lenth && tr % lenth != 0)
            expand('r', 'u', tr - lenth + 1);
        if (jug(tr + 1, '0') && tr % lenth != 0)
            expand('r', tr + 1);
        Sleep(100);
    }
    if (x == 'l')
    {
        if (tr % lenth != 1)
            show(tr - 1);
        if ((tr - 1) / lenth != width && tr % lenth != 1)
            show(tr + lenth - 1);
        if (tr > lenth && tr % lenth != 1)
            show(tr - lenth - 1);
        if (jug(tr - 1, '0') && tr % lenth != 1)
            expand('l', tr - 1);
        if (jug(tr + lenth - 1, '0') && (tr - 1) / lenth != width && tr % lenth != 1)
            expand('l', 'd', tr + lenth - 1);
        if (jug(tr - lenth - 1, '0') && tr > lenth && tr % lenth != 1)
            expand('l', 'u', tr - lenth - 1);
        Sleep(100);
    }
    if (x == '0')
    {
        expand('d', tr);
        expand('r', tr);
        expand('u', tr);
        expand('l', tr);
    }
}
void cell::expand(char x, char y, int tr)
{
    if ((x == 'u' && y == 'r') || (x == 'r' && y == 'u'))
    {
        expand('u', tr);
        expand('r', tr);
    }
    if ((x == 'd' && y == 'r') || (x == 'r' && y == 'd'))
    {
        expand('d', tr);
        expand('r', tr);
    }
    if ((x == 'u' && y == 'l') || (x == 'l' && y == 'u'))
    {
        expand('u', tr);
        expand('l', tr);
    }
    if ((x == 'd' && y == 'l') || (x == 'l' && y == 'd'))
    {
        expand('d', tr);
        expand('l', tr);
    }
}
void cell::sign(int tr)
{
    if (curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == '#')
        curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] = 'M';
    else if (curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == 'M')
        curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] = '?';
    else if (curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] == '?')
        curtain[tr + lenth + 3 + 2 * ((tr - 1) / lenth)] = '#';
    PR1();
}
void cell::detect(int i)
{
    if (curtain[i + lenth + 3 + 2 * ((i - 1) / lenth)] == '#')
        return;
    int cnt = 0;
    if (jugc(i + 1, 'M') && i % lenth != 0)
        cnt++;
    if (jugc(i - 1, 'M') && i % lenth != 1)
        cnt++;
    if (jugc(i + lenth, 'M') && (i - 1) / lenth != width)
        cnt++;
    if (jugc(i - lenth, 'M') && i > lenth)
        cnt++;
    if (jugc(i + lenth + 1, 'M') && (i - 1) / lenth != width && i % lenth != 0)
        cnt++;
    if (jugc(i + lenth - 1, 'M') && (i - 1) / lenth != width && i % lenth != 1)
        cnt++;
    if (jugc(i - lenth - 1, 'M') && i > lenth && i % lenth != 1)
        cnt++;
    if (jugc(i - lenth + 1, 'M') && i > lenth && i % lenth != 0)
        cnt++;
    if (cnt == cells[i + lenth + 3 + 2 * ((i - 1) / lenth)] - '0')
    {
        if (!jugc(i + 1, 'M') && i % lenth != 0)
            process(i + 1);
        if (!jugc(i - 1, 'M') && i % lenth != 1)
            process(i - 1);
        if (!jugc(i + lenth, 'M') && (i - 1) / lenth != width)
            process(i + lenth);
        if (!jugc(i - lenth, 'M') && i > lenth)
            process(i - lenth);
        if (!jugc(i + lenth + 1, 'M') && (i - 1) / lenth != width && i % lenth != 0)
            process(i + lenth + 1);
        if (!jugc(i + lenth - 1, 'M') && (i - 1) / lenth != width && i % lenth != 1)
            process(i + lenth - 1);
        if (!jugc(i - lenth - 1, 'M') && i > lenth && i % lenth != 1)
            process(i - lenth - 1);
        if (!jugc(i - lenth + 1, 'M') && i > lenth && i % lenth != 0)
            process(i - lenth + 1);
    }
    PR1();
}
void cell::fin()
{
    if (!flg1)
    {
        if (flg2)
        {
            cout << "You are victorious." << endl;
        }
        else
        {
            cout << "You have lost." << endl;
        }
        PR2();
    }
}

#endif